using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

namespace IQIGame.Onigao.Game
{
    public abstract class UIBaseWindow : UIBaseNode
    {
        public static readonly IReadOnlyDictionary<Type, Func<bool>> NeedRecoverDelegates = new Dictionary<Type, Func<bool>>();

        private bool _uiBgAdapterChecked;
        private UIBackgroundAdapter _uiBgAdapter;
        private ExImage _imgInternalUICover = null;
        protected UIBaseData _data;

        public abstract IUICreateConfig createConfig { get; }
        public UIWindowSetting winSetting { get; internal set; } = new UIWindowSetting();
        public bool isCanBindCav { get; private set; } = true;
        public ExCanvas canvasEx { get; private set; }
        public override ResLoader resLoader => this.winSetting.resloader;
        public UIBackgroundAdapter uiBgAdapter
        {
            get
            {
                if (!_uiBgAdapterChecked)
                {
                    _uiBgAdapter = this.gameObject.GetComponentInChildren<UIBackgroundAdapter>(true);
                    _uiBgAdapterChecked = true;
                }
                return _uiBgAdapter;
            }
        }

        public virtual UIBaseWindow InitWinSettings(int sortOrder, ResLoader loader, IUICreateConfig cfg = null)
        {
            IUICreateConfig curCfg = cfg != null ? cfg : this.createConfig;
            this.winSetting.Init(curCfg, sortOrder, loader);
            return this;
        }

        public virtual bool ResetWinSettingSortOrder(int sortOrder)
        {
            int lastSort = this.winSetting.sortOrder;
            bool isChanged = sortOrder != lastSort;
            if (isChanged)
            {
                this.winSetting.sortOrder = sortOrder;
                this.ReCavsInfo();
            }
            return isChanged;
        }

        public virtual bool EscapeBack()
        {
            if (this.gameObject == null)
                return false;

            var btnBack = this.gameObject.GetComponentInChildren<ExButtonBack>(true);
            bool isState = (btnBack != null && btnBack.gameObject.activeSelf);
            if (isState)
                ExecuteEvents.Execute<ISubmitHandler>(btnBack.gameObject, new PointerEventData(EventSystem.current), ExecuteEvents.submitHandler);
            return isState;
        }

        public void Init(GameObject gameObject)
        {
            Init(gameObject, this, null);
        }

        protected override void InitDisplay(GameObject gameObject)
        {
            base.InitDisplay(gameObject);
            this.ReCavsInfo();
        }

        public async UniTask TrtSetBGRawImageTexture()
        {
            if (createConfig.activeBlurBg && createConfig.blurDownSampling > 0)
            {
                if (this.uiBgAdapter != null)
                {
                    await this.uiBgAdapter.GenBlurRtAndApply(createConfig.prefabName, createConfig.blurDownSampling);
                }
                else
                {
                    LogGame.LogError("UI Config里开启了模糊背景，但UI上找不到挂载了UIBackgroundAdapter组件的背景图片节点");
                }
            }
        }

        private void ReCavsInfo()
        {
            if (this.gameObject == null)
            {
                return;
            }
            if (this.isCanBindCav)
            {
                if (this.canvasEx == null)
                    this.canvasEx = this.gameObject.GetOrAdd<ExCanvas>();
            }

            if (this.canvasEx != null)
                this.canvasEx.SetSortOrder(this.winSetting.sortLayerName, this.winSetting.sortOrder);
        }

        public UIBaseData GetLeaveData()
        {
            var data = OnGetLeaveData();
            if (data != null)
            {
                data.isRecover = true;
            }
            return data;
        }

        protected virtual UIBaseData OnGetLeaveData()
        {
            return null;
        }

        public void Show(UIBaseData data)
        {
            this.Show();
            this.ClearData();
            this._data = data;
            this.OnShow(data);
        }

        /// <summary>
        /// 实现基类UIBaseNode的方法，执行顺序在OnShow(object data)之前
        /// UIBaseWindow的子类不用重写该方法，重写它是冗余的，重写OnShow(object data)即可
        /// </summary>
        protected override void OnShow()
        {

        }

        protected abstract void OnShow(UIBaseData data);

        public override void Hide()
        {
            base.Hide();
            ClearData();
        }

        private void ClearData()
        {
            if (_data != null)
            {
                ClassPool.PutAutoType(_data);
                _data = null;
            }
        }

        public override void Dispose()
        {
            this.canvasEx = null;
            this._uiBgAdapterChecked = false;
            this._uiBgAdapter = null;
            var resLoader = this.winSetting.resloader;
            this.winSetting.resloader = null;
            base.Dispose();
            resLoader?.Put2Pool();
        }

        protected virtual bool IsFullScreen()
        {
            return this.winSetting?.isFullScreen ?? false;
        }

        public bool IsFullScreenAndActive()
        {
            return this.isActive && this.IsFullScreen();
        }

        /// <summary>
        /// UIWindow的内部遮挡
        /// </summary>
        /// <param name="isActive"></param>
        public void SetInternalUICover(bool isActive)
        {
            if (_imgInternalUICover == null && !isActive)
            {
                return;
            }
            if (_imgInternalUICover == null)
            {
                var gobj = new GameObject("InternalUICover", typeof(ExImage));
                Transform trsf = gobj.transform;
                trsf.SetParent(this.transform, false);
                RectTransform rectGo = trsf as RectTransform;
                Vector2 anchorHalf = Vector2.one * 0.5f;
                rectGo.anchorMin = anchorHalf;
                rectGo.anchorMax = anchorHalf;
                rectGo.localPosition = Vector2.zero;
                rectGo.sizeDelta = ManagerCenter.UI.BackgroundStretchSize;
                _imgInternalUICover = gobj.GetOrAdd<ExImage>();
                _imgInternalUICover.color = new Color(0, 0, 0, 1f / 255);
            }
            _imgInternalUICover.transform.SetAsLastSibling();
            _imgInternalUICover.SetActive(isActive);
        }

        protected void RegisterNeedRecoverFunc(Func<bool> func)
        {
            (NeedRecoverDelegates as Dictionary<Type, Func<bool>>)[this.GetType()] = func;
        }
    }
}

